package org.best.array;

import java.io.*;

/**
 * 稀疏数组工具类,用于二维数组和稀疏数组的转换,后续需优化
 */
public class sparseArrayUtil {
    /**
     * 将稀疏数组转换为二维数组
     *
     * @param array
     * @return
     */
    public static int[][] toDimensionArray(int[][] array) {
        //首先根据稀疏数组的00 和 01 定义一个二维数组
        int[][] ints = new int[array[0][0]][array[0][1]];
        //遍历稀疏数组
        for (int i = 1; i < array.length; i++) {
            ints[array[i][0]][array[i][1]] = array[i][2];
        }
        return ints;
    }

    /**
     * 将二维数组转换为稀疏数组
     *
     * @param array
     * @return
     */
    public static int[][] toSparseArray(int[][] array) {
        //首先获取二维数组中有效的个数
        int count = 0;
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[0].length; j++) {
                if (array[i][j] != 0) {
                    count++;
                }
            }
        }
        //定义一个稀疏数组
        int[][] sparseArray = new int[count + 1][3];
        sparseArray[0][0] = array.length;
        sparseArray[0][1] = array[0].length;
        sparseArray[0][2] = count;
        //遍历二维数组,将有效数据放到稀疏数组里
        int sparseCount = 1;
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[0].length; j++) {
                if (array[i][j] != 0) {
                    sparseArray[sparseCount][0] = i;
                    sparseArray[sparseCount][1] = j;
                    sparseArray[sparseCount][2] = array[i][j];
                    sparseCount++;
                }
            }
        }
        return sparseArray;
    }

    /**
     * 将二维数组转成稀疏数组序列化到文件中,指定文件名
     *
     * @param array
     * @param fileName 文件名称
     * @return
     */
    public static boolean serializableDimensionArray(int[][] array, String fileName) {
        File file = new File(fileName);
        int[][] sparseArray = toSparseArray(array);
        return serializableArray(sparseArray, file);
    }

    /**
     * 将二维数组转成稀疏数组序列化到文件中,指定文件
     *
     * @param array
     * @param file  指定文件
     * @return
     */
    public static boolean serializableDimensionArray(int[][] array, File file) {
        int[][] sparseArray = toSparseArray(array);
        return serializableArray(sparseArray, file);
    }

    private static boolean serializableArray(int[][] array, File file) {
        ObjectOutputStream objectOutputStream = null;
        try {
            objectOutputStream = new ObjectOutputStream(new FileOutputStream(file));
            objectOutputStream.writeObject(array);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (objectOutputStream != null) {
                try {
                    objectOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 将文件中读取到的稀疏数组反序列化得到二维数组
     *
     * @param array
     * @param fileName 文件名称
     * @return
     */
    public static int[][] unSerializableSparseArray(String fileName) {
        File file = new File(fileName);
        return unSerializableArray(file);
    }

    /**
     * 将文件中读取到的稀疏数组反序列化得到二维数组
     *
     * @param file 文件
     * @return
     */
    public static int[][] unSerializableSparseArray(File file) {
        return unSerializableArray(file);
    }

    private static int[][] unSerializableArray(File file) {
        ObjectInputStream objectInputStream = null;
        int[][] readArray;
        int[][] dimensionArray = null;
        try {
            objectInputStream = new ObjectInputStream(new FileInputStream(file));
            readArray = (int[][]) objectInputStream.readObject();
            dimensionArray = toDimensionArray(readArray);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (objectInputStream != null) {
                try {
                    objectInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return dimensionArray;
    }
}
